package com.epoch.base.export;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

public class CsvExporter extends AbstractTextExporter {
    private static final char UTF8_BOM_CHAR = 65279;
    private final String deli;
    private final boolean withUtf8Bom;

    public CsvExporter(String deli, boolean withUtf8Bom) {
        super();
        this.deli = deli;
        this.withUtf8Bom = withUtf8Bom;
    }

    @Override
    protected void doTextExport(BufferedWriter writer, Collection<?> data, List<HeadMeta> headMetas,
        Map<Integer, IExportConvertor> indexCvtorMap, Map<String, IExportConvertor> fieldCvtorMap,
        Map<String, Object> params) throws IOException, ExportException {
        if (CollectionUtils.isNotEmpty(headMetas)) {
            this.outputUtf8Bom(writer);
            int c = 0;
            int cols = headMetas.size();
            for (; c < cols; c++) {
                HeadMeta meta = headMetas.get(c);
                String title = meta.getTitle();
                writer.write(this.buildCsvField(title));
                if (c < cols - 1) {
                    writer.write(this.deli);
                }
            }
            writer.newLine();
            if (data != null) {
                int r = 0;
                for (Object rowData : data) {
                    for (c = 0; c < cols; c++) {
                        HeadMeta meta = headMetas.get(c);
                        String field = meta.getField();
                        IExportConvertor cvt = indexCvtorMap == null ? null : indexCvtorMap.get(Integer.valueOf(c));
                        if (cvt == null) {
                            cvt = fieldCvtorMap == null ? null : fieldCvtorMap.get(field);
                        }
                        Object val = this.obtainFieldVal(rowData, indexCvtorMap, fieldCvtorMap, field, r, c);
                        String valStr = "";
                        if (val instanceof Date) {
                            valStr = ExportConstant.DATETIME_FORMAT.format((Date)val);
                        } else if (val != null) {
                            valStr = val.toString();
                        }
                        writer.write(this.buildCsvField(val == null ? "" : valStr));
                        if (c < cols - 1) {
                            writer.write(this.deli);
                        }
                    }
                    writer.newLine();
                    r++;
                }
            }
        }
    }

    @Override
    public String getFileNameExt() {
        return ".csv";
    }

    private void outputUtf8Bom(BufferedWriter writer) throws IOException {
        if (this.withUtf8Bom) {
            writer.write(CsvExporter.UTF8_BOM_CHAR);
        }
    }

    private String buildCsvField(String str) {
        String result = str;
        if (result != null) {
            result = result.replace("\"", "\"\"");
            if (StringUtils.containsAny(result, this.deli, "\r", "\n")) {
                result = "\"" + result + "\"";
            }
        }
        return result;
    }
}
